// zoj2352
// 题意：给定n个点，求凸包，并从(0, 0)开始按逆时针顺序输出凸包。
//
// 题解：其实就是凸包。
//
// run: $exec < input
// opt: 0
// flag: -g
// std: c++98
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <vector>

template <class T>
struct point
{
	typedef T value_type;
	point(value_type x, value_type y) : x(x), y(y) {};
	point() {};
	value_type x, y;
};

int const maxn = 100;

typedef int cord_type;
std::vector<point<cord_type> > points(maxn);
std::vector<point<cord_type> > stack(maxn);

template <class T>
int signum(T const & x)
{
	return (x < 0 ? -1 : x > 0 ? + 1 : 0);
}

template <class T>
T ccw(point<T> const & a, point<T> const & b, point<T> const & c)
{
	return signum((long long)(b.x - a.x) * (c.y - a.y) - (long long)(b.y - a.y) * (c.x - a.x));
}

template <class T>
struct cmp
{
	bool operator()(point<T> const & a, point<T> const & b)
	{
		return a.y < b.y || (a.y == b.y && a.x < b.x);
	}
};

int main()
{
	int T;
	std::cin >> T;
	for (int ti = 1; ti <= T; ti++) {
		int n = 1;
		std::cin >> points[0].x >> points[0].y;

		std::string s;
		std::getline(std::cin, s);
		for (; std::getline(std::cin, s) && s.size(); n++) {
			std::stringstream buf;
			buf << s;
			buf >> points[n].x >> points[n].y;
		}

		std::sort(points.begin(), points.begin() + n, cmp<cord_type>());
		int top = 0;
		for (int i = 0; i < n; i++) {
			while (top >= 2 && ccw(stack[top - 2], stack[top - 1], points[i]) < 0)
				top--;
			stack[top++] = points[i];
		}
		int t = top + 1;
		for (int i = n - 2; i >= 0; i--) {
			while (top >= t && ccw(stack[top - 2], stack[top - 1], points[i]) < 0)
				top--;
			stack[top++] = points[i];
		}

		// the perimeter of the convex hull
		int orign = 0, m = top - 1;
		for (int i = 0; i < m; i++)
			if (!stack[i].x && !stack[i].y) { orign = i; break; }
		for (int i = 0; i < m; i++)
			std::cout << "(" << stack[(orign + i) % m].x << "," << stack[(orign + i) % m].y << ")\n";
		if (ti < T) std::cout << '\n';
	}
}

